package com.ghck.server.service.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ghck.server.dao.TestAnswerItemMapper;
import com.ghck.server.dao.TestAnswerMapper;
import com.ghck.server.dao.TestQuestionAnswerMapper;
import com.ghck.server.model.TestAnswer;
import com.ghck.server.model.TestAnswerItem;
import com.ghck.server.model.TestQuestionAnswer;
import com.ghck.server.model.TestQuestionItem;
import com.ghck.server.model.query.TestAnswerQuery;
import com.ghck.server.model.request.PaperReq;
import com.ghck.server.model.request.QuestionAnswerReq;
import com.ghck.server.model.request.QuestionReq;
import com.ghck.server.model.request.TestQuestionItemReq;
import com.ghck.server.model.response.TestAnswerRes;
import com.ghck.server.model.response.TestCategoryDictRes;
import com.ghck.server.model.response.TestQuestionRes;
import com.ghck.server.service.TestAnswerService;
import com.ghck.server.service.TestCategoryDictService;
import com.ghck.server.service.TestQuestionItemService;
import com.ghck.server.service.TestQuestionService;
import com.ghck.server.utils.IntegerUtil;
import com.ghck.server.utils.RedisKeyUtil;

/**
 * 测试记录  <br>
 * t_test_answer <br>
 * v1.0 2016-05-01
 */
@Service
@Transactional
public class TestAnswerServiceImpl implements TestAnswerService {

	private static final Logger logger = LoggerFactory.getLogger(TestAnswerServiceImpl.class);

	@Autowired
	private TestAnswerMapper testAnswerMapper;

	@Autowired
	private TestAnswerItemMapper testAnswerItemMapper;

	@Autowired
	private TestQuestionAnswerMapper testQuestionAnswerMapper;

	@Autowired
	private TestCategoryDictService testCategoryDictService;

	@Autowired
	private RedisTemplate<String,Object> template;

	@Autowired
	TestQuestionService testQuestionService;
	
	@Autowired
	TestQuestionItemService testQuestionItemService;

	/**
	 *根据ID删除 测试记录
	 */
	@Override
	public Integer deleteTestAnswerById(Integer id){
		return testAnswerMapper.deleteById(id);
	}

	/**
	 *新增 测试记录
	 */
	@Override
	@Transactional
	public Integer batchInsertTestAnswer(List<? extends TestAnswer> testAnswers){
		Integer count = testAnswerMapper.batchInsert(testAnswers);
		return count;
	}
	/**
	 *新增 测试记录
	 */
	@Override
	@Transactional
	public Integer insertTestAnswer(TestAnswer domain){
		Integer id = testAnswerMapper.insert(domain);
		return id;
	}

	/**
	 *更新 测试记录
	 */
	@Override
	@Transactional
	public Integer updateTestAnswer(TestAnswer domain){
		testAnswerMapper.update(domain);
		Integer id = domain.getId();
		return id;
	}

	/**
	 *根据ID查询 测试记录
	 */
	public TestAnswer findTestAnswerById(Integer id){
		TestAnswer result = testAnswerMapper.findById(id);
		if(result!=null){
			result.dealWith();
		}
		return result;
	}

	/**
	 *通过query 查询 测试记录
	 */
	public List<TestAnswerRes> findTestAnswerByQuery(TestAnswerQuery query){
		long start = System.currentTimeMillis();
		long end = start;
		query.dealWith();
		testCategoryDictService.syncInRedis(false);
		//后去之类
		String key2 = RedisKeyUtil.paperSampleHashKey();
		if(IntegerUtil.isPositiveInteger(query.getParentId())){
			String key3 = RedisKeyUtil.parentIdMapPaperSampleChildren();
			String hashKey = RedisKeyUtil.domainIdKey(query.getParentId());
			HashOperations<String, String, List<Integer>> hOperations = template.opsForHash();
			query.setCategoryIdList(hOperations.get(key3, hashKey));
		}
		
		if(logger.isDebugEnabled()){
			end = System.currentTimeMillis();
			logger.debug("|==================>findTestAnswerByQuery 1. cost:{}ms",(end-start));
			start = end;
		}
		List<TestAnswerRes> result = testAnswerMapper.findByQuery(query);
		if(logger.isDebugEnabled()){
			end = System.currentTimeMillis();
			logger.debug("|==================>testAnswerMapper.findByQuery. cost:{}ms",(end-start));
			start = end;
		}
		List<String> hashkeys = new ArrayList<>();
		if(CollectionUtils.isNotEmpty(result)) {
			for (TestAnswer testAnswer : result) {
				testAnswer.dealWith();
				String hashKey = RedisKeyUtil.domainIdKey(testAnswer.getCategoryId());
				hashkeys.add(hashKey);
			}
			if (CollectionUtils.isNotEmpty(hashkeys)) {
				HashOperations<String, String, TestCategoryDictRes> hOperations = template.opsForHash();
				List<TestCategoryDictRes> categorys = hOperations.multiGet(key2, hashkeys);
				if (CollectionUtils.isNotEmpty(categorys)) {
					Map<Integer, TestCategoryDictRes> map = new HashMap<Integer, TestCategoryDictRes>();
					for (TestCategoryDictRes testCategoryDictRes : categorys) {
						map.put(testCategoryDictRes.getId(), testCategoryDictRes);
					}
					for (TestAnswerRes testAnswer : result) {
						if(map.containsKey(testAnswer.getCategoryId())){
							testAnswer.setPaperName(map.get(testAnswer.getCategoryId()).getName());
						}
					}
				}
			}
		}
		if(logger.isDebugEnabled()){
			end = System.currentTimeMillis();
			logger.debug("|==================>testAnswerMapper.loadName. cost:{}ms",(end-start));
			start = end;
		}
		return result;
	}	

	/**
	 *通过query count总条数
	 */
	public Integer countTestAnswerByQuery(TestAnswerQuery query){
		query.dealWith();
		Integer result = testAnswerMapper.countByQuery(query);
		return result;
	}

	/**
	 * 通过ids查询
	 */
	public List<TestAnswer> findTestAnswerByIds(List<Integer> ids){

		List<TestAnswer> result = testAnswerMapper.findByIds(ids);
		if(CollectionUtils.isNotEmpty(result)) {
			for (TestAnswer testAnswer : result) {
				testAnswer.dealWith();
			}
		}
		return result;
	}

	@Override
	public TestAnswerRes submitPaper(Integer userId, Integer paperId,String servStationId, QuestionReq que) {
		Integer answerId = 0;
		TestCategoryDictRes paper = testCategoryDictService.findPaperById(paperId);
		Map<Integer, TestQuestionItem> idMapTestQuestionItem = new HashMap<Integer, TestQuestionItem>();
		if(paper!=null && que.getAnswers()!=null && que.getAnswers().length>0){ //组织item映射
			List<TestQuestionRes> questionList = paper.getTestQuestionResList();
			if (CollectionUtils.isNotEmpty(questionList)) {
				for (TestQuestionRes testQuestionRes : questionList) {
					List<TestQuestionItem>  testQuestionItemList = testQuestionRes.getTestQuestionItemList();
					if (CollectionUtils.isNotEmpty(testQuestionItemList)) {
						for (TestQuestionItem testQuestionItem : testQuestionItemList) {
							idMapTestQuestionItem.put(testQuestionItem.getId(), testQuestionItem);
						}
					}
				}
			}

			//需要入库的题目选项
			List<TestAnswerItem> answerItemInsert = new ArrayList<TestAnswerItem>();
			//需要入库的题目
			List<TestQuestionAnswer> answerQuestionInsert = new ArrayList<TestQuestionAnswer>();
			//需要入库的试卷
			TestAnswer answerInsert = new TestAnswer();
			int totalScore = 0;
			for (QuestionAnswerReq questionAnswerReq : que.getAnswers()) {
				Integer questionId = questionAnswerReq.getQuestionId();
				Integer[] itemIds = questionAnswerReq.getItemIds();
				int questionScore = 0;
				boolean hasZeroItem = false;
				if(ArrayUtils.isNotEmpty(itemIds)){
					for (Integer itemId : itemIds) {
						TestQuestionItem qItem = idMapTestQuestionItem.get(itemId);
						if(qItem!=null){
							TestAnswerItem item = new TestAnswerItem();
							item.setQuestionItemId(itemId);
							item.setScore(qItem.getScore());
							if(qItem.getScore().intValue()==0){
								hasZeroItem = true;
							}
							if(hasZeroItem){
								questionScore = 0;
							}else{
								questionScore += qItem.getScore().intValue();
							}
							answerItemInsert.add(item);
						}
					}
					totalScore += questionScore;
				}
				TestQuestionAnswer questionAnswer = new TestQuestionAnswer();
				questionAnswer.setQuestionId(questionId);
				questionAnswer.setScore(questionScore);
				answerQuestionInsert.add(questionAnswer);
			}

			//封装答案
			answerInsert.setScore(totalScore);
			answerInsert.setCategoryId(paperId);
			answerInsert.setUserId(userId);
			answerInsert.setStationId(que.getStationId());

			//医生建议+测评结果
			double rate = totalScore*1.0/paper.getScore();
			if(rate>=0.9){
				answerInsert.setDoctorSuggest("非常棒，继续保持");
				answerInsert.setResultDesc("是思想家而非实干家，抽象思维能力强，求知欲强，肯动脑，善思考，但有时不愿动手");
			}else if(rate>=0.8){
				answerInsert.setDoctorSuggest("还可以，不过得加强锻炼");
				answerInsert.setResultDesc("注重内心的感受，关注如何创造性的解决问题，一般具有较强的创新精神，而不愿，循规蹈矩");
			}else if(rate>=0.6){
				answerInsert.setDoctorSuggest("基本达标，有点危险，务必加强锻炼");
				answerInsert.setResultDesc("通常具有领导才能，能够影响说服他人共同达到组织或个人的目标");
			}else if(rate<0.6){
				answerInsert.setDoctorSuggest("没救了");
				answerInsert.setResultDesc("在职业发展过程中，可以充分发挥善于运用抽象思维逻辑推理等能力来分析解决问题的 优势");
			}

			testAnswerMapper.insert(answerInsert);
			answerId = answerInsert.getId();

			Integer beginQuestionId = null;
			Map<Integer, TestQuestionAnswer> questionIdMapTestQuestionAnswer = new HashMap<Integer, TestQuestionAnswer>();
			if (CollectionUtils.isNotEmpty(answerQuestionInsert)) {
				if (CollectionUtils.isNotEmpty(answerQuestionInsert)) {
					for (TestQuestionAnswer testQuestionAnswer : answerQuestionInsert) {
						testQuestionAnswer.setAnswerId(answerId);
					}
				}
				testQuestionAnswerMapper.batchInsert(answerQuestionInsert);
				beginQuestionId = answerQuestionInsert.get(0).getId();
				List<TestQuestionAnswer> answers_1 = testQuestionAnswerMapper.findByAnswerIdStartId(answerId,beginQuestionId);
				if (CollectionUtils.isNotEmpty(answers_1)) {
					for (TestQuestionAnswer testQuestionAnswer : answers_1) {
						questionIdMapTestQuestionAnswer.put(testQuestionAnswer.getQuestionId(), testQuestionAnswer);
					}
				}
			}

			if (CollectionUtils.isNotEmpty(answerItemInsert)) {
				if (CollectionUtils.isNotEmpty(answerItemInsert)) {
					for (TestAnswerItem testAnswerItem : answerItemInsert) {
						TestQuestionItem testQuestionItem = idMapTestQuestionItem.get(testAnswerItem.getQuestionItemId());
						if(testQuestionItem!=null){
							Integer test_question_id = testQuestionItem.getParentId();
							TestQuestionAnswer testQuestionAnswer = questionIdMapTestQuestionAnswer.get(test_question_id);
							if(testQuestionAnswer!=null){
								testAnswerItem.setQuestionAnswerId(testQuestionAnswer.getId());
							}
						}
					}
				}
				testAnswerItemMapper.batchInsert(answerItemInsert);
			}
		}

		TestAnswerRes res = testAnswerMapper.findResById(answerId);

		//缓存
		String key = RedisKeyUtil.userLastQuestionnaireValueKey(userId);
		template.opsForValue().set(key, res);
//		template.expire(key, 7, TimeUnit.DAYS);

		return res;
	}

	@Override
	public TestAnswerRes findMyLastTestAnswerRes(Integer userId){
		TestAnswerRes res = null;
		String key = RedisKeyUtil.userLastQuestionnaireValueKey(userId);
		if(template.hasKey(key)){
			res = (TestAnswerRes) template.opsForValue().get(key);
		}else{
			res = testAnswerMapper.findMyLastTestAnswerRes(userId);
			template.opsForValue().set(key, res);
//			template.expire(key, 7, TimeUnit.DAYS);
		}
		return res;
	}
	

	@Override
	public List<TestAnswerRes> findAnswer(Integer userId, Integer parentId, Integer start, Integer limit) {
		return testAnswerMapper.findAnswerByUserIdParentId(userId, parentId, start, limit);
	}

	@Override
	@Transactional
	public Integer addParer(PaperReq req) {
		testCategoryDictService.insertTestCategoryDict(req);
		Integer paperId = req.getId();
		for (QuestionReq questionReq : req.getQuestions()) {
			questionReq.setCategoryId(paperId);
			
			testQuestionService.insertTestQuestion(questionReq);
			
			for (TestQuestionItemReq item : questionReq.getItems()) {
				item.setParentId(questionReq.getId());
				testQuestionItemService.insertTestQuestionItem(item);
			}
		}
		return paperId;
	}
	
	
	@Override
	public Integer modifyParer(PaperReq req) {
		testCategoryDictService.updateTestCategoryDict(req);
		Integer paperId = req.getId();
		for (QuestionReq questionReq : req.getQuestions()) {
			questionReq.setCategoryId(paperId);
			if(IntegerUtil.isPositiveInteger(questionReq.getId())){//修改
				testQuestionService.updateTestQuestion(questionReq);
			}else{
				testQuestionService.insertTestQuestion(questionReq);
			}
			
			for (TestQuestionItemReq item : questionReq.getItems()) {
				item.setParentId(questionReq.getId());
				if(IntegerUtil.isPositiveInteger(item.getId())){//修改
					testQuestionItemService.updateTestQuestionItem(item);
				}else{
					testQuestionItemService.insertTestQuestionItem(item);
				}
			}
		}
		return paperId;
	}
	
	
}	